package com.atguigu.tingshu.account.service.impl;

import cn.hutool.core.lang.Assert;
import com.atguigu.tingshu.account.mapper.UserAccountDetailMapper;
import com.atguigu.tingshu.account.mapper.UserAccountMapper;
import com.atguigu.tingshu.account.service.RechargeInfoService;
import com.atguigu.tingshu.account.service.UserAccountService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.account.RechargeInfo;
import com.atguigu.tingshu.model.account.UserAccount;
import com.atguigu.tingshu.model.account.UserAccountDetail;
import com.atguigu.tingshu.vo.account.AccountDeductVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Slf4j
@Service
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {

    private final UserAccountDetailMapper userAccountDetailMapper;
    private final RechargeInfoService rechargeInfoService;

    public UserAccountServiceImpl(UserAccountDetailMapper userAccountDetailMapper, RechargeInfoService rechargeInfoService) {
        this.userAccountDetailMapper = userAccountDetailMapper;
        this.rechargeInfoService = rechargeInfoService;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void saveUserAccount(Long userId) {
        // 初始化账户记录，保存账户信息（user_account）
        UserAccount userAccount = new UserAccount();
        userAccount.setUserId(userId);
        userAccount.setTotalAmount(new BigDecimal(100));
        userAccount.setLockAmount(new BigDecimal(0));
        userAccount.setAvailableAmount(new BigDecimal(100));
        userAccount.setTotalIncomeAmount(new BigDecimal(100));
        userAccount.setTotalPayAmount(new BigDecimal(0));
        this.baseMapper.insert(userAccount);
        // 新增账户变动历史（首次注册赠送100点金额）
        this.saveUserAccountDetail(
                userId,
                "初始化账户，赠送金额：100",
                SystemConstant.ACCOUNT_TRADE_TYPE_DEPOSIT,
                userAccount.getAvailableAmount(),
                null
        );

    }

    @Override
    public void saveUserAccountDetail(Long userId, String title, String tradeType, BigDecimal amount, String orderNo) {
        UserAccountDetail userAccountDetail = new UserAccountDetail();
        userAccountDetail.setUserId(userId);
        userAccountDetail.setTitle(title);
        userAccountDetail.setTradeType(tradeType);
        userAccountDetail.setAmount(amount);
        userAccountDetail.setOrderNo(orderNo);
        this.userAccountDetailMapper.insert(userAccountDetail);
    }

    @Override
    public Double getAvailableAmountByUserId(Long userId) {
        UserAccount userAccount = this.baseMapper.selectOne(new LambdaQueryWrapper<UserAccount>()
                .eq(UserAccount::getUserId, userId)
                .select(UserAccount::getAvailableAmount));
        Assert.notNull(userAccount, "用户账户不存在");
        return userAccount.getAvailableAmount().doubleValue();
    }

    @Override
    public void checkAndDeduct(AccountDeductVo accountDeductVo) {
        // 1.检查及扣减余额
        int count = this.baseMapper.checkAndDeduct(accountDeductVo);
        if (count == 0) {
            throw new GuiguException(ResultCodeEnum.ACCOUNT_LESS);
        }

        // 2.保存账户变动日志
        this.saveUserAccountDetail(
                accountDeductVo.getUserId(),
                accountDeductVo.getContent(),
                SystemConstant.ACCOUNT_TRADE_TYPE_MINUS,
                accountDeductVo.getAmount(),
                accountDeductVo.getOrderNo()
        );
    }

    @Override
    public void updateAccountOnPaySuccess(String orderNo) {
        // 1.根据订单编号查询充值信息
        RechargeInfo rechargeInfo = this.rechargeInfoService.getRechargeInfoByOrderNo(orderNo);
        // 2.判断充值信息。如果充值信息不存在或者充值状态为已支付，则返回
        if (rechargeInfo == null) {
            throw new GuiguException(ResultCodeEnum.DATA_ERROR);
        }
        if (SystemConstant.ORDER_STATUS_PAID.equals(rechargeInfo.getRechargeStatus())) {
            return;
        }
        // 3.更新充值信息状态为已支付
        rechargeInfo.setRechargeStatus(SystemConstant.ORDER_STATUS_PAID);
        this.rechargeInfoService.updateById(rechargeInfo);

        // 4.更新充值信息所属用户的账户信息
        UserAccount userAccount = this.baseMapper.selectOne(new LambdaQueryWrapper<UserAccount>()
                .eq(UserAccount::getUserId, rechargeInfo.getUserId()));
        userAccount.setAvailableAmount(userAccount.getAvailableAmount().add(rechargeInfo.getRechargeAmount()));
        userAccount.setTotalIncomeAmount(userAccount.getTotalIncomeAmount().add(rechargeInfo.getRechargeAmount()));
        userAccount.setTotalAmount(userAccount.getTotalAmount().add(rechargeInfo.getRechargeAmount()));
        this.baseMapper.updateById(userAccount);
    }

    @Override
    public Page<UserAccountDetail> getUserAccountDetailPage(Page<UserAccountDetail> page, Long userId, String tradeType) {
        LambdaQueryWrapper<UserAccountDetail> queryWrapper = new LambdaQueryWrapper<UserAccountDetail>()
                .eq(UserAccountDetail::getUserId, userId)
                .eq(UserAccountDetail::getTradeType, tradeType)
                .orderByDesc(UserAccountDetail::getId);
        return this.userAccountDetailMapper.selectPage(page, queryWrapper);
    }
}
